import type { Tab } from '#/browser/entities/tab.entity'

// 导入所需的模块和类型
import { app, BaseWindow, WebContents } from 'electron'
import { installWindowShortcuts } from '#/browser/services/shortcut.installer'

import type { WatchHandle } from '@vue/reactivity'
import { ViewLayerController } from '#/browser/controllers/viewLayer.controller'
import { SeparateWindowManager } from '#/browser/managers/separateWindow.manager'
import { TabManager } from '#/browser/managers/tab.manager'

import { getWindowBackgroundColor } from '#/utils/paths'
import { getLayoutTab } from '#/utils/tabs'
import { createBaseWindow } from '#/utils/windows'
import { createStorageState, systemState, systemTheme } from 'global-state'
import { WINDOW_STYLE_CONSTANTS } from '~shared/constants/layout'
import { createBrowserIpc } from '#/utils/ipc'
import { WindowState } from '~types/global-state'

// 初始化主窗口状态管理器
export const windowState = createStorageState(
  'windowBounds',
  {
    width: 1600,
    height: 1000,
    isMaximized: false
  } as WindowState,
  2
)

// 初始化其他窗口状态管理器
export const otherWindowState = createStorageState(
  'otherWindowBounds',
  {
    width: 1600,
    height: 1000,
    isMaximized: false
  } as WindowState,
  2
)

/**
 * 浏览器类 - 负责管理单个浏览器实例的完整生命周期
 *
 * 主要职责：
 * 1. 浏览器实例的创建、配置和销毁管理
 * 2. 浏览器布局和视图边界的动态调整
 * 3. 标签页控制器的协调和事件传播
 * 4. 浏览器状态的持久化存储和恢复
 * 5. 系统主题变化和浏览器大小调整的响应处理
 *
 * @class Browser
 * @author 黄敏
 * @version 2.0.0
 * @since 2025-07-21
 */
export class WindowController {
  /** Electron主浏览器实例 */
  readonly electronWindow: BaseWindow

  /** 布局视图，用于显示浏览器布局内容 */
  readonly layoutTab: Tab
  /** 标签页管理器实例 */
  readonly tabManager: TabManager

  /** 视图层控制器实例，负责视图边界的动态调整 */
  readonly viewLayerController: ViewLayerController

  /** 标识当前浏览器是否为主浏览器 */
  readonly isMainWindow: boolean

  /** 独立窗口管理器实例 */
  private separateWindowManager: SeparateWindowManager

  /** 浏览器关闭时的回调函数 */
  private windowClosedCallback?: () => void

  // 取消监听器
  unwatchs: WatchHandle[] = []

  private browserIpc!: ReturnType<typeof createBrowserIpc>

  get id() {
    return this.electronWindow.id
  }

  /**
   * 浏览器构造函数 - 初始化浏览器实例和相关组件
   * @param isMainWindow - 是否为主浏览器
   * @param initializationParams - 初始化参数，可以是标签数组或字符串
   * @description 创建Electron浏览器实例，初始化标签页控制器，设置布局视图
   */
  constructor(isMainWindow: boolean, initializationParams?: Tab[] | string) {
    this.isMainWindow = isMainWindow // 确定浏览器类型

    // 创建Electron浏览器实例
    const store = this.isMainWindow ? windowState : otherWindowState

    this.electronWindow = createBaseWindow(store, {
      titleBarStyle: 'hidden',
      minWidth: WINDOW_STYLE_CONSTANTS.MIN_WIDTH,
      minHeight: WINDOW_STYLE_CONSTANTS.MIN_HEIGHT
    })

    // 创建布局视图，用于显示浏览器布局
    this.layoutTab = getLayoutTab()

    this.layoutTab.view.webContents.on('dom-ready', () => {
      this.electronWindow.show()
    })

    // 创建独立窗口管理器
    this.separateWindowManager = new SeparateWindowManager(this.electronWindow)

    this.separateWindowManager.on('open-windows:change', openWindows => {
      this.browserIpc.send('open-separate-windows:change', openWindows)
    })

    this.tabManager = new TabManager({
      isMainWindow,
      layoutTab: this.layoutTab,
      separateWindowManager: this.separateWindowManager,
      data: initializationParams
    })

    this.browserIpc = createBrowserIpc(this.layoutTab.view.webContents)

    // 设置标签页管理器的窗口关闭回调 - 当所有标签页关闭时自动关闭窗口
    this.tabManager.setWindowCloseCallback(() => {
      if (!this.electronWindow.isDestroyed()) {
        //
        this.electronWindow.close()
      }
    })

    // 初始化事件监听和主题设置
    this.setupEventListeners()
    // 设置 MessageChannel
    this.setupMessageChannel()

    // 初始化视图层与边界控制（已合并到 ViewLayerController）
    this.viewLayerController = new ViewLayerController(this)

    // 安装应用级（窗口级）快捷键
    this.setupShortcuts()
  }

  /**
   * 处理layoutTab与它的渲染进程的通讯
   * */
  setupMessageChannel() {
    this.browserIpc.on('addTab', (tab, type) => {
      this.tabManager.createTabs(type ?? 'top', tab)
    })

    this.browserIpc.on('closeTabs', tabIds => {
      this.tabManager.onCloseTabsById(tabIds)
    })

    this.browserIpc.on('hideTab', tabId => {
      const win = this.separateWindowManager.getWindowByTabId(tabId)
      if (win) {
        win.minimize()
      } else {
        this.tabManager.hideTabById(tabId)
      }
    })

    this.browserIpc.on('setActiveTab', tabId => {
      if (tabId) {
        this.tabManager.onSwitch(tabId)
      } else {
        this.tabManager.clearActive()
      }
    })

    this.browserIpc.on('setLayer', isOnTop => {
      this.viewLayerController.setLayoutView(isOnTop)
    })

    // 窗口控制
    this.browserIpc.on('minimizeWindow', () => {
      this.electronWindow.minimize()
    })

    this.browserIpc.on('maximizeWindow', () => {
      this.electronWindow.maximize()
    })

    this.browserIpc.on('unmaximizeWindow', () => {
      this.electronWindow.unmaximize()
    })

    this.browserIpc.on('closeWindow', () => {
      this.electronWindow.close()
    })

    // 创建分组
    this.browserIpc.on('createGroup', urls => {
      this.tabManager.createTabGroup(urls)
    })

    this.browserIpc.syncOn('getBrowserTopTabs', () => {
      return this.tabManager.topTabController.getBrowserTabs()
    })
    this.browserIpc.syncOn('getBrowserRightTabs', () => {
      return this.tabManager.rightTabController.getBrowserTabs()
    })
    this.browserIpc.syncOn('getBrowserLeftTabs', () => {
      return this.tabManager.leftTabController?.getBrowserTabs() ?? []
    })

    this.browserIpc.syncOn('getActiveTabId', () => {
      return this.tabManager.getActiveTabId()
    })
    // 是否主窗口
    this.browserIpc.syncOn('isMainWindow', () => {
      return this.isMainWindow
    })
    this.browserIpc.syncOn('getSeparateOpenIds', () => {
      return this.separateWindowManager.getOpenWindows()
    })

    this.browserIpc.syncOn('isWindowMaximized', () => {
      return this.electronWindow.isMaximized()
    })
  }

  /**
   * 检查当前浏览器是否包含指定的WebContents
   *
   * @param webContents - 要检查的WebContents实例
   * @returns 如果当前浏览器包含该WebContents则返回true，否则返回false
   *
   * @description 用于确定WebContents的归属，包括布局视图和标签页视图
   */
  getTabByWebContents(webContents: WebContents): boolean {
    // 检查是否为布局视图的WebContents
    if (this.layoutTab.view.webContents === webContents) {
      return true
    }

    // 检查是否为标签页控制器管理的WebContents
    return this.tabManager.getTabByWebContents(webContents)
  }

  /**
   * 清理浏览器资源
   *
   * @private
   * @description 关闭所有WebContents视图，清理标签页控制器，销毁状态管理器
   */
  private cleanupBrowserResources(): void {
    for (const unwatch of this.unwatchs) {
      try {
        unwatch()
      } catch (error) {
        console.error('清理监听器时发生错误:', error)
      }
    }
    this.unwatchs = []

    // 清理视图层/边界控制器
    this.viewLayerController.cleanup()

    // 清理布局视图
    if (this.layoutTab && !this.layoutTab.isDestroyed) {
      this.layoutTab.destroy()
    }

    // 清理标签页管理器
    this.tabManager.destroy() // 清理控制器
  }

  /**
   * 注册浏览器关闭回调函数
   *
   * @param callback - 浏览器关闭时执行的回调函数
   *
   * @description 允许外部代码在浏览器关闭时执行清理操作
   */
  onClosed(callback: () => void): void {
    this.windowClosedCallback = callback
  }

  /**
   * 设置事件监听器和主题初始化
   *
   * @private
   * @description 注册浏览器生命周期事件监听器和系统主题变化监听
   */
  private setupEventListeners(): void {
    // 监听系统主题变化，动态更新浏览器样式
    const handleThemeChange = () => {
      this.electronWindow.setBackgroundColor(getWindowBackgroundColor())
    }
    this.unwatchs.push(systemTheme.watch(handleThemeChange))
    this.unwatchs.push(systemState.watch('theme', handleThemeChange))

    // 监听窗口最大化状态变化
    this.electronWindow.on('maximize', () => {
      this.browserIpc.send('window:maximize-state', true)
    })

    this.electronWindow.on('unmaximize', () => {
      this.browserIpc.send('window:maximize-state', false)
    })

    // 监听浏览器关闭事件
    this.electronWindow.on('closed', () => {
      this.cleanupBrowserResources()

      if (this.isMainWindow) {
        // 主浏览器关闭，退出应用
        app.quit()
      } else {
        // 执行外部注册的关闭回调
        this.windowClosedCallback?.()
      }
    })
  }

  /**
   * 安装窗口级快捷键：对布局和顶部标签页的 WebContents 统一监听
   */
  private setupShortcuts(): void {
    installWindowShortcuts({
      win: this.electronWindow,
      layoutTab: this.layoutTab,
      tabManager: this.tabManager
    })
  }
}
